/*
 * @(#)XfvhdlParameter.java        3.0                        2004/09/14
 *
 * This file is part of Xfuzzy 3.0, a design environment for fuzzy logic
 * based systems.
 *
 * (c) 2000 IMSE-CNM. The authors may be contacted by the email address:
 *                    xfuzzy-team@imse.cnm.es
 *
 * Xfuzzy is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * Xfuzzy is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

package xfuzzy.xfvhdl;

/**
* Clase que gestiona los par�metros que se le pasan a la aplicaci�n desde
* la l�nea de comandos.
* @author Jos� Mar�a �vila Maireles, <b>e-mail</b>: josavimai@alum.us.es
* @version 3.0
*/
public class XfvhdlParameter {

   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
   //	  ATRIBUTOS PRIVADOS DE LA CLASE 				            
   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
   /* En args almaceno los par�metros que me pasan por la l�nea de 
    * comandos. */
   private String args[];

   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
   //				CONSTRUCTOR DE LA CLASE					 	   
   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//	
   /**
    * Constructor de XFvhdlParameter
    * @param c Son los par�metros que me pasan por la l�nea de comandos.
    */
   public XfvhdlParameter(String c[]) {

      if (c.length == 0) {
         XfvhdlError err = new XfvhdlError(6);
         err.show();
         System.exit(-1);
      }

      args = new String[c.length];

      for (int i = 0; i < c.length; i++) {
         args[i] = new String(c[i]);
      }
   }

   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
   //				M�TO_DOS P�BLICOS DE LA CLASE				        
   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
   /**
   * M�todo que trata los par�metros que se le pasan a la aplicaci�n 
   * desde la l�nea de comandos.
   * @param args[] Array que contiene los par�metros.
   */
   public void loadParameter() {

      // Averiguo el directorio desde el que se lanza la aplicaci�n
      try {
         XfvhdlProperties.userDirectory =
            System.getProperty("user.dir", ".");
         XfvhdlProperties.fileSeparator =
            System.getProperty("file.separator", "\\");
      } catch (Exception e) {
      }

      // Miro primero si es una ejecuci�n en consola o en una ventana:
      if (numParameter() == 1 && findParameterBoolean("-g") == 1)
         XfvhdlProperties.inWindow = true;
      else { // En caso de ejecuci�n por consola

         // Busco el nombre del fichero XFL.
         XfvhdlProperties.ficheroXFL = findParameter(0);
         XfvhdlProperties.fileDir = null;

         // Busco el prefijo de los ficheros de salida y adem�s el 
         // directorio donde los colocar�.
         if (findParameter("-o") != null) {
            XfvhdlProperties.outputDirectory =
               getDirectory(findParameter("-o"));
            XfvhdlProperties.outputFile = getPrefix(findParameter("-o"));
         }

         // Busco el valor de la variable N.
         if (findParameterInt("-N") != -1) {
            XfvhdlProperties.N = findParameterInt("-N");
         }

         // Busco el valor de la variable grad.
         if (findParameterInt("-d") != -1) {
            XfvhdlProperties.grad = findParameterInt("-d");
            // Desde la l�nea de comandos busco "-d", y lo almaceno en
            // la variable grad. Es una inconsistencia arrastrada desde 
            // la versi�n 2 de xfvhdl.
         }

         //	Busco el valor de la variable K.
         if (findParameterInt("-K") != -1) {
            XfvhdlProperties.K = findParameterInt("-K");
         }

         //	Busco el valor de la variable P.
         if (findParameterInt("-P") != -1) {
            XfvhdlProperties.P = findParameterInt("-P");
            // Si P obtiene alg�n valor implica que estamos ante 
            // C�lculo Aritm�tico.
            XfvhdlProperties.calcArithmetic = true;
         }

         //	Averiguo si hay que generar ficheros complementarios de 
         // informaci�n.
         if (findParameterBoolean("-cf") == 1) {
            XfvhdlProperties.complementaryFiles = true;
            // Averiguo si hay que escribir nulos en rulesmem.dat
            if (findParameterBoolean("-withnull") == 1)
               XfvhdlProperties.withNull = true;
         }

         // Busco el directorio donde se encuentran las librerias VHDL.
         if (findParameter("-L") != null) {
            XfvhdlProperties.libraryDirectory = findParameter("-L");
         }

         // Busco si el tipo de memoria es RAM-Block
         if (findParameterBoolean("-Mb") == 1) {
            if ((findParameterBoolean("-Md") != -1)
               || (findParameterBoolean("-Mo") != -1)
               || (findParameterBoolean("-Ml") != -1)) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(18);
            } else {
               XfvhdlProperties.memoryType = "RAM-Block";
            }
         }

         // Busco si el tipo de memoria es RAM-Distributed
         if (findParameterBoolean("-Md") == 1) {
            if ((findParameterBoolean("-Mb") != -1)
               || (findParameterBoolean("-Mo") != -1)
               || (findParameterBoolean("-Ml") != -1)) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(18);
            } else {
               XfvhdlProperties.memoryType = "RAM-Distributed";
            }
         }

         // Busco si el tipo de memoria es ROM
         if (findParameterBoolean("-Mo") == 1) {
            if ((findParameterBoolean("-Md") != -1)
               || (findParameterBoolean("-Mb") != -1)
               || (findParameterBoolean("-Ml") != -1)) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(18);
            }
         }

         // Busco si el tipo de memoria es Combinational Logic
         if (findParameterBoolean("-Ml") == 1) {
            if ((findParameterBoolean("-Md") != -1)
               || (findParameterBoolean("-Mo") != -1)
               || (findParameterBoolean("-Mb") != -1)) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(18);
            } else {
               XfvhdlProperties.memoryType = "Combinational Logic";
            }
         }

         // Busco si el Map Effort que se usar� ser� High
         if (findParameterBoolean("-Eh") == 1) {
            if (findParameterBoolean("-El") != -1) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(22);
            } else {
               XfvhdlProperties.mapEffort = "HIGH_MAP_EFFORT";
            }
         }

         // Busco si el Map Effort que se usar� ser� Low
         if (findParameterBoolean("-El") == 1) {
            if (findParameterBoolean("-Eh") != -1) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(22);
            }
         }

         // Averiguo si se precisa de optimizaci�n por �rea
         if (findParameterBoolean("-Oa") == 1) {
            XfvhdlProperties.areaOptimization = true;
         }

         // Averiguo si se precisa de optimizaci�n por velocidad
         if (findParameterBoolean("-Os") == 1) {
            XfvhdlProperties.speedOptimization = true;
         }

         // Busco si la Herramienta de S�ntesis es Synopsys FPGA Express
         if (findParameterBoolean("-Ce") == 1) {
            if ((findParameterBoolean("-Cx") != -1)
               || (findParameterBoolean("-Cc") != -1)) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(23);
            } else {
               XfvhdlProperties.synthesisTool = "FPGA_Express";
            }
         }

         // Busco si la Herramienta de S�ntesis es Synopsys FPGA 
         // Compiler 2
         if (findParameterBoolean("-Cc") == 1) {
            if ((findParameterBoolean("-Cx") != -1)
               || (findParameterBoolean("-Ce") != -1)) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(23);
            } else {
               XfvhdlProperties.synthesisTool = "FPGA_Compiler_2";
            }
         }

         // Busco si la Herramienta de S�ntesis es Xilinx XST
         if (findParameterBoolean("-Cx") == 1) {
            if ((findParameterBoolean("-Cc") != -1)
               || (findParameterBoolean("-Ce") != -1)) {
               XfvhdlError err = new XfvhdlError();
               err.newWarning(23);
            }
         }

         // Busco el Part Type -the target FPGA device for the 
         // synthesis tool-
         if (findParameter("-Dv") != null) {
            XfvhdlProperties.partType = findParameter("-Dv");
         }

         // Busco el Target -the target FPGA family for Synopsys 
         // synthesis tool-
         if (findParameter("-T") != null) {
            XfvhdlProperties.target = findParameter("-T");
         }

         // Averiguo si hay que lanzar la herramienta de s�ntesis al 
         // terminar
         if (findParameterBoolean("-S") == 1) {
            XfvhdlProperties.synthesis = true;
         }

         // Averiguo si hay que lanzar la herramienta de implementaci�n 
         // al terminar
         if (findParameterBoolean("-I") == 1) {
            XfvhdlProperties.implementation = true;
         }

         // Averiguo si la memoria de reglas no se implementa en una ROM
         if (findParameterBoolean("-inROM") == 1) {
            XfvhdlProperties.rulesMemWithROM = true;
         }
      }
   }

   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
   //	M�TO_DOS PRIVADOS DE LA CLASE							    
   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

   /**
    * M�todo que busca si me han pasado el par�metro c por la l�nea de 
    * comandos.
    * @param c Par�metro que estoy buscando.
    * @return Devuelve el siguiente par�metro al que busco o null si 
    * no lo encuentro.
    */
   private String findParameter(String c) {
      int l = args.length;
      int i = 0;
      boolean enc = false;

      while (i < l) {
         if (args[i].equalsIgnoreCase(c) && (i + 1) < l) {
            return (args[i + 1]);
         } else if (args[i].equalsIgnoreCase(c) && !((i + 1) < l)) {
            enc = true;
         }

         if (!((i + 1) < 1) && enc) {
            XfvhdlError err = new XfvhdlError();
            err.newWarning(7, args[i]);
         }

         i++;
      }

      return (null);
   }

   /**
    * M�todo que busca si me han pasado el par�metro c por la l�nea de 
    * comandos.
    * @param c Par�metro que estoy buscando.
    * @return Devuelve un ENTERO que es el siguiente par�metro al que 
    * busco o null si no lo encuentro.
    */
   private int findParameterInt(String c) {
      int l = args.length;
      int i = 0;
      boolean enc = false;

      while (i < l) {
         if (args[i].equalsIgnoreCase(c) && (i + 1) < l) {
            return (Integer.parseInt(args[i + 1]));
         } else if (args[i].equalsIgnoreCase(c) && !((i + 1) < l)) {
            enc = true;
         }

         if (!((i + 1) < 1) && enc) {
            XfvhdlError err = new XfvhdlError();
            err.newWarning(7, args[i]);
         }

         i++;
      }
      return (-1);
   }

   /**
    * M�todo que busca si me han pasado el par�metro c por la l�nea de 
    * comandos.
    * @param c Par�metro que estoy buscando.
    * @return Devuelve 1 si encuentra el parametro y -1 si no lo 
    * encuentra.
    */
   private int findParameterBoolean(String c) {
      int l = args.length;
      int i = 0;
      boolean enc = false;

      while (i < l) {
         if (args[i].equalsIgnoreCase(c)) {
            enc = true;
         }
         i++;
      }
      if (!enc)
         return (-1);
      else
         return (1);
   }

   /**
    * M�todo que me devuelve el par�metro n�mero p pasado por la 
    * l�nea de comandos.
    * @param p N�mero del par�metro que estoy buscando.
    * @return Devuelve el par�metro n�mero p o null si no existe.
    */
   private String findParameter(int p) {
      if (args.length < p) {
         new XfvhdlError(8);
         return (null);
      } else {
         return (args[p]);
      }
   }

   /**
    * M�todo que me devuelve el n�mero de par�metros pasados por la 
    * l�nea de comandos.
    * @return Devuelve el n�mero de par�metros.
    */
   private int numParameter() {
      return args.length;
   }

   /**
    * M�todo que me devuelve el prefijo del nombre de los ficheros 
    * dada una ruta.
    * @return Devuelve el prefijo del nombre de los ficheros.
    */
   private String getPrefix(String in) {
      int c = 0;
      String out = new String();

      for (int i = 0; i < in.length(); i++) {
         if (in.charAt(i) == XfvhdlProperties.fileSeparator.charAt(0))
            c = i + 1;
      }

      out = in.substring(c);

      if (out.length() < 1) {
         out = XfvhdlProperties.OUTPUT_FILE_DEFAULT;
         XfvhdlError xerr = new XfvhdlError();
         xerr.newWarning(21);
      }

      return out;
   }

   /**
    * M�todo que me devuelve el directorio dada una ruta.
    * @return Devuelve el directorio.
    */
   private String getDirectory(String in) {
      int c = 0;
      String out = new String();

      for (int i = 0; i < in.length(); i++) {
         if (in.charAt(i) == XfvhdlProperties.fileSeparator.charAt(0))
            c = i + 1;
      }

      out = in.substring(0, c);

      if (out.length() < 1) {
         out = XfvhdlProperties.OUTPUT_DIRECTORY_DEFAULT;
      }

      return out;
   }

} // Fin de la clase.
